
const DETALUT_KEY = '__NO_OBJECT_kEY'
type NotificationKey = string;
type NotificationName = string;
type NotificationObject = string;
type Dictionary<T = any> = { [key: NotificationKey]: T }
type NotificationInfo = {
    name: NotificationName;
    object?: NotificationObject
} | NotificationName
type Callback = (info: { userInfo?: Dictionary } & NotificationInfo) => void
type NotificationObserver = {
    callback: Array<Callback>
}

type Cache = Dictionary<Dictionary<NotificationObserver>>
class Notification {
    private map: Cache;
    constructor() {
        this.map = {}
    }

    post(info: NotificationInfo, params?: Dictionary) {
        const { name, object } = typeof info === 'string' ? { name: info, object: '' } : info
        const value = this.map[name]
        if (!info) {
            return
        }

        const key = object || DETALUT_KEY
        const data = value?.[key]
        if (data?.callback) {
            data.callback.forEach(cb => cb({ name, object, userInfo: params }))
        }
    }

    observer(info: NotificationInfo, callback: Callback) {
        const { name, object } = typeof info === 'string' ? { name: info, object: '' } : info
        if (!this.map[name]) {
            this.map[name] = {}
        }

        const key = object || DETALUT_KEY
        if (!this.map[name][key]) {
            this.map[name][key] = {
                callback: []
            }
        }

        this.map[name][key].callback.push(callback)
    }


    removeObserver(name: NotificationName, object?: NotificationObject) {
        if (!name) {
            return
        }
        try {
            if (!object) {
                delete this.map[name]
                return
            }
            if (this.map[name]) {
                delete this.map[name][object]
            }
        } catch (error) {
            // temp
        }
    }
}

const NotificationCenter = new Notification();
export default NotificationCenter

export type {
    NotificationKey,
    NotificationName,
    NotificationObject
}
